home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / BDTTABLE.PAK / TABLE.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  16KB  |  545 lines

  1. // (C) Copyright 1996, Borland International
  2. //
  3. // table.cpp - VDBT PITTtabe example
  4. /*******************************************************************************
  5. This example demonstrates how hook up to a database table and then navigate
  6. through it using the VDBT PITtable object and the COM classes.  The user can
  7. navigate through the table using the Main Menu items or via the keyboard.  Only
  8. one record will be displayed at a time.
  9.  
  10.  
  11.     SETTING UP TO USE AN EVENT HANDLER
  12.  
  13.     Visual Database Tools uses event sources and event sinks (or     handlers) to
  14.    encapsulate everything necessary for repsonding    to event.  The general     steps
  15.    are:
  16.     1.  Identify the source that will be the source of the events you wish to 
  17.         handle, in this particular example, TDataSource.  This is done in the
  18.        MainCreateMsg function.
  19.     2.  Define the event sink to handle the event.  This is done as part of the
  20.         EventHandler class.
  21.     3.  Connect the event sink to the event handler.  This is done as part of
  22.          The EventHandle constructor.
  23.     4.  Connect the event source to the event sink.  This is done in the
  24.          MainCreateMsg function.
  25.  
  26.  
  27. The BIOLIFE table in the diveplan database is used by default.  A different
  28. database and table can be specified on as command line arguments.
  29.  
  30. The files needed to build this program are:
  31.  
  32. table.cpp            Source file for application
  33. table.rc                Resource file for application
  34. table.ico            Icon file for application
  35. table16/32.def        module definition file for 16bit and 32bit target respectively
  36. makefile                makefile for command-line tools build
  37. table.ide            BCW 5.0 project file to build both 32bit and 16bit    targets.
  38. *******************************************************************************/
  39.  
  40. #define INITGUID
  41. #include <windowsx.h>
  42. #include "resource.h"
  43. //pragma hdrstop used here because bdtc.h unavoidably initializes data that will
  44. //prevent pre-compiled headers from being used.
  45. #pragma hdrstop
  46. #include <vdbt\bdtc.h>
  47.  
  48. //******************************************************************************
  49.  
  50. #define NOTUSED( x )        ((void)(long) (x))
  51.  
  52. #define DATABASENAME "DivePlan"
  53. #define TABLENAME "biolife.db"
  54.  
  55. #define MAIN_CLASS_NAME    "Main Class"
  56.  
  57. //******************************************************************************
  58. // function prototypes
  59.  
  60. BOOL RegisterMainClass( HINSTANCE hInstance );
  61.  
  62. HWND CreateMainWindow( HINSTANCE hInstance, LPSTR lpszCmdLine, int cmdShow );
  63.  
  64. extern "C" LRESULT CALLBACK _export MainWndProc( HWND hwnd, UINT msg,
  65.                                                                 WPARAM wParam, LPARAM lParam );
  66.                                                 
  67. void MainCreateMsg( HWND hwnd, LPSTR lpszCmdLine );
  68.  
  69. void MainPaintMsg( HWND hwnd );
  70.  
  71. void GetAndDrawGraphic( HDC hdc, PITField field, int top, int left, int width,
  72.                                                                                          int height );
  73.  
  74. void GetAndDisplayMemo( HDC hdc, PITField field, int top, int left, int width,
  75.                                                                                          int height );
  76.  
  77. void DrawPrettyText(HDC hdc, PITAnyString PrintString, int top, int left,
  78.                                                                         int width,    int height);
  79.                                                       
  80. BOOL MainCommandMsg( HWND hwnd, WPARAM wParam, LPARAM lParam );
  81.  
  82. void MainKeyDownMsg( HWND hwnd, WPARAM wParam );
  83.  
  84. void MainDestroyMsg( HWND hwnd );
  85.  
  86. //******************************************************************************
  87.  
  88. int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int cmdShow )
  89. {
  90.     if (! hPrevInstance)
  91.         if (! RegisterMainClass(hInstance))
  92.             return 0;
  93.  
  94.     CreateMainWindow(hInstance, lpszCmdLine, cmdShow);
  95.  
  96.     MSG msg;
  97.     while (GetMessage(&msg, (HWND) 0, 0, 0))
  98.     {
  99.         TranslateMessage(&msg);
  100.         DispatchMessage(&msg);
  101.     }
  102.  
  103.     return 0;
  104. }
  105.  
  106. //******************************************************************************
  107.  
  108. BOOL RegisterMainClass( HINSTANCE hInstance )
  109. {
  110.     WNDCLASS wndClass;
  111.  
  112.     wndClass.style = CS_HREDRAW | CS_VREDRAW;
  113.     wndClass.lpfnWndProc = MainWndProc;
  114.     wndClass.cbClsExtra = 0;
  115.     wndClass.cbWndExtra = sizeof(PITTable) + sizeof(PPITField) + sizeof(PITDataSource);
  116.     wndClass.hInstance = hInstance;
  117.     wndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN));
  118.     wndClass.hCursor = LoadCursor((HINSTANCE) 0, IDC_ARROW);
  119.     wndClass.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
  120.     wndClass.lpszMenuName = MAKEINTRESOURCE(IDM_MAIN);
  121.     wndClass.lpszClassName = MAIN_CLASS_NAME;
  122.  
  123.     return RegisterClass(&wndClass);
  124. }
  125.  
  126. //******************************************************************************
  127.  
  128. HWND CreateMainWindow( HINSTANCE hInstance, LPSTR lpszCmdLine, int cmdShow )
  129. {
  130.     char    szTitle[30 + 1];
  131.     HWND    hwnd;
  132.  
  133.     LoadString(hInstance, IDS_MAINTITLE, szTitle, 30);
  134.     hwnd = CreateWindow(MAIN_CLASS_NAME, szTitle, WS_TILEDWINDOW,
  135.         CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  136.         (HWND) 0, (HMENU) 0, hInstance, lpszCmdLine);
  137.  
  138.     if (hwnd)
  139.     {
  140.         ShowWindow(hwnd, cmdShow);
  141.         UpdateWindow(hwnd);
  142.     }
  143.  
  144.     return hwnd;
  145. }
  146.  
  147. //******************************************************************************
  148.  
  149. extern "C" LRESULT CALLBACK _export MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  150. {
  151.     switch (msg)
  152.     {
  153.         case WM_CREATE:
  154.             MainCreateMsg( hwnd, (LPSTR) ((LPCREATESTRUCT) lParam)->lpCreateParams );
  155.             break;
  156.  
  157.         case WM_PAINT:
  158.             MainPaintMsg(hwnd);
  159.             break;
  160.  
  161.         case WM_COMMAND:
  162.             if (! MainCommandMsg(hwnd, wParam, lParam))
  163.                 return DefWindowProc(hwnd, msg, wParam, lParam);
  164.             break;
  165.  
  166.         case WM_KEYDOWN:
  167.             MainKeyDownMsg(hwnd, wParam);
  168.             break;
  169.  
  170.         case WM_DESTROY:
  171.             MainDestroyMsg(hwnd);
  172.             PostQuitMessage(0);
  173.             break;
  174.  
  175.         default:
  176.             return DefWindowProc(hwnd, msg, wParam, lParam);
  177.     }
  178.  
  179.     return 0L;
  180. }
  181.  
  182.  
  183. /*******************************************************************************
  184. OnDataChange
  185.   When the data changes (the user has navigated to a new record) it invalidates
  186.   the right hand side of the window and force a repaint.  The left hand side of
  187.   the windows does not need to be repainted because it holds data the is static
  188.   the entire time the app is running.
  189. *******************************************************************************/
  190. void STDAPICALLTYPE _export OnDataChange( long data, PITDataSource, PITField )
  191. {
  192.     HWND hwnd = (HWND) data;
  193.     if (hwnd)
  194.     {
  195.         RECT rc;
  196.         GetClientRect( hwnd, &rc );
  197.         rc.left = rc.right/2;
  198.         InvalidateRect( hwnd, &rc, TRUE );
  199.     }
  200. }
  201.  
  202.  
  203. /*******************************************************************************
  204. MainCreateMsg.
  205.     This initializes the main window and the database table.  Things to note are
  206.    the create of the TTable object, the try block that opens the database table,
  207.    the create of the datasource object and the attachment to the OnDataChange
  208.    event.
  209. *******************************************************************************/
  210. void MainCreateMsg(HWND hwnd, LPSTR lpszCmdLine)
  211. {
  212.     // Parse the command line for the alias and table names.
  213.  
  214.     LPSTR databaseName = DATABASENAME;
  215.     LPSTR tableName = TABLENAME;
  216.     if (*lpszCmdLine)
  217.     {
  218.         LPSTR space = strchr( lpszCmdLine, ' ');
  219.         if (space)
  220.         {
  221.             *space = '\0';
  222.             tableName = space+1;
  223.             databaseName = lpszCmdLine;
  224.         }
  225.     }
  226.  
  227.     // Update the window's title bar with the database and table names.
  228.  
  229.     char    szTitle[30 + 100 + 1];
  230.     int len = GetWindowText( hwnd, szTitle, sizeof(szTitle) );
  231.     wsprintf( szTitle+len, " - :%s:%s", databaseName, tableName );
  232.     SetWindowText( hwnd, szTitle );
  233.  
  234.     // Create the TTable object.
  235.  
  236.     PITTable table = CreateITTable();
  237.     if (table)
  238.     {
  239.         // Put the database and table name properties, open the table.
  240.  
  241.         try
  242.         {
  243.             PITAnyString d = CreateITAnyString();
  244.             d->put_AsStringBuf( databaseName );
  245.             table->put_DatabaseName( d );
  246.             d->Release();
  247.  
  248.             PITAnyString t = CreateITAnyString();
  249.             t->put_AsStringBuf( tableName );
  250.             table->put_TableName( t );
  251.             t->Release();
  252.  
  253.             table->Open();
  254.         }
  255.         catch (BDTException e)
  256.         {
  257.             e.Show( "processing WM_CREATE" );
  258.             table->Release();
  259.             table = NULL;
  260.         }
  261.         SetWindowLong( hwnd, 0, (LONG) table );
  262.  
  263.         if (table)
  264.         {
  265.             // Allocate space to hold the field object pointers.
  266.  
  267.             int count = table->get_FieldCount();
  268.             PPITField fields = new PITField [ count ];
  269.             int i;
  270.             for (i = 0; i < count; i++)
  271.                 fields[i] = table->get_Fields( i );
  272.             SetWindowLong( hwnd, 4, (LONG) fields );
  273.  
  274.             // Create a datasource object and attach to the OnDataChange event.
  275.  
  276.             PITDataSource datasource = CreateITDataSource();
  277.             if (datasource)
  278.             {
  279.                 datasource->put_DataSet( table );
  280.                 datasource->AttachOnDataChange( OnDataChange, (long) hwnd );
  281.                 SetWindowLong( hwnd, 8, (LONG) datasource );
  282.             }
  283.         }
  284.     }
  285. }
  286.  
  287.  
  288. /*******************************************************************************
  289. MainPaintMsg
  290.     This function will repaint the window with the (static) table field
  291.     names on the left side and the (dynamic) field entries on the right.
  292.     The table name.
  293. *******************************************************************************/
  294. void MainPaintMsg(HWND hwnd)
  295. {
  296.     PAINTSTRUCT ps;
  297.     RECT rc;
  298.  
  299.     BeginPaint( hwnd, &ps );
  300.     GetClientRect( hwnd, &rc );
  301.  
  302.     PITTable table = (PITTable) GetWindowLong( hwnd, 0 );
  303.     if (table)
  304.     {
  305.         int count = table->get_FieldCount();
  306.         if (count)
  307.         {
  308.             int width = rc.right/2;
  309.             int height = rc.bottom/count;
  310.  
  311.             PPITField fields = (PPITField) GetWindowLong( hwnd, 4 );
  312.             if (fields)
  313.             {
  314.                 // Paint the field names on the left side of the window, the
  315.                 // field values on the right side of the window.
  316.  
  317.                 int i;
  318.                 for (i = 0; i < count; i++)
  319.                 {
  320.                     if (fields[i])
  321.                     {
  322.                         PITAnyString n = fields[i]->get_FieldName();
  323.                         DrawPrettyText( ps.hdc, n, i*height, 0, width, height );                  
  324.                         n->Release();
  325.  
  326.                         if (fields[i]->get_DataType() == ftGraphic)
  327.                         {
  328.                             GetAndDrawGraphic( ps.hdc, fields[i], width, i*height,
  329.                                                                              width, height );
  330.                         }
  331.                      else if (fields[i]->get_DataType() == ftMemo)
  332.                   {
  333.                             GetAndDisplayMemo( ps.hdc, fields[i], i*height, width,
  334.                                                                              width, height );
  335.                   }
  336.                   else
  337.                         {
  338.                             PITAnyString t = fields[i]->get_Text();
  339.                             DrawPrettyText(ps.hdc, t, i*height, width, width, height);
  340.                             t->Release();
  341.                         }
  342.                     }
  343.                 }
  344.             }
  345.         }
  346.     }
  347.  
  348.     EndPaint(hwnd, &ps);
  349. }
  350.  
  351.  
  352. /*******************************************************************************
  353. GetAndDrawGraphic
  354.     This will function will accurately display a graphic field that is in the
  355.    current record.   Note that the SaveToBitmap method will save the bitmap from
  356.    the graphic field to the hbitmap and hpalette handles.
  357. *******************************************************************************/
  358. void GetAndDrawGraphic( HDC hdc, PITField field, int x, int y, int w, int h )
  359. {
  360.     // Use the SaveToBitmap method to get the bitmap and palette handles.
  361.  
  362.     HBITMAP hbm = 0;
  363.     HPALETTE hpal = 0;
  364.     field->SaveToBitmap( &hbm, &hpal );
  365.     if (hbm)
  366.     {
  367.         HDC hdcTemp = CreateCompatibleDC( hdc );
  368.         if (hdcTemp)
  369.         {
  370.             BITMAP bm;
  371.             GetObject( hbm, sizeof(BITMAP), &bm );
  372.             HBITMAP hbmPrev = SelectBitmap( hdcTemp, hbm );
  373.             StretchBlt( hdc, x, y, w, h,
  374.                             hdcTemp, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY );
  375.             SelectBitmap( hdcTemp, hbmPrev );
  376.             DeleteDC( hdcTemp );
  377.         }
  378.         DeleteBitmap( hbm );
  379.     }
  380.     if (hpal)
  381.         DeletePalette( hpal );
  382. }
  383.  
  384. /*******************************************************************************
  385. GetAndDisplayMemo
  386.     This function will accurately display a memo field that is in the current
  387.    record.   Note that the DrawPrettyText function will perform word-wrap so
  388.    that as much of the memo as possible will be displayed.
  389. *******************************************************************************/
  390. void GetAndDisplayMemo( HDC hdc, PITField field, int top, int left, int width,
  391.                                                                                         int height )
  392. {
  393.     // create a stream for the memo
  394.     PITMemoryStream stream = CreateITMemoryStream();
  395.     if (stream)
  396.     {
  397.         // save the memo to the stream
  398.         field->SaveToStream( stream );
  399.         stream->put_Position( 0 );
  400.         PITStrings strings = CreateITStrings();
  401.         if (strings)
  402.         {
  403.             strings->LoadFromStream( stream );
  404.             PITAnyString t = strings->get_Text();
  405.             if (t)
  406.             {
  407.                DrawPrettyText(hdc, t, top, left, width, height);
  408.                 t->Release();
  409.             }
  410.             strings->Release();
  411.         }
  412.  
  413.         stream->Release();
  414.     }
  415. }
  416.  
  417. void DrawPrettyText(HDC hdc, PITAnyString PrintString, int top, int left,
  418.                                                                             int width, int height)
  419. {
  420.                 RECT rc;
  421.                 rc.left = left;
  422.                 rc.top = top;
  423.                 rc.right = rc.left + width;
  424.                 rc.bottom = rc.top + height;
  425.                 DrawText( hdc, PrintString->get_Buffer(), PrintString->get_Length(),
  426.                          &rc, DT_TOP | DT_LEFT | DT_WORDBREAK | DT_NOPREFIX );
  427. }
  428.  
  429. /*******************************************************************************
  430. MainCommandMsg
  431.     This handles all of the commands that come for the Main Menu to navigate
  432.    through the table. All other WM_COMMAND messages are passed onto Windows.
  433. *******************************************************************************/
  434. BOOL MainCommandMsg(HWND hwnd, WPARAM wParam, LPARAM lParam)
  435. {
  436.     NOTUSED( lParam );
  437.     // Process navigation commands from the menu.
  438.  
  439.     PITTable table = (PITTable) GetWindowLong( hwnd, 0 );
  440.     if (table)
  441.     {
  442.         switch (GET_WM_COMMAND_ID(wParam, lParam))
  443.         {
  444.             case IDM_NAV_FIRST:
  445.                 table->First();
  446.                 break;
  447.             case IDM_NAV_PRIORSET:
  448.                 table->MoveBy(-5);
  449.                 break;
  450.             case IDM_NAV_PRIOR:
  451.                 table->Prior();
  452.                 break;
  453.             case IDM_NAV_NEXT:
  454.                 table->Next();
  455.                 break;
  456.             case IDM_NAV_NEXTSET:
  457.                 table->MoveBy(5);
  458.                 break;
  459.             case IDM_NAV_LAST:
  460.                 table->Last();
  461.                 break;
  462.             default:
  463.                 return FALSE;
  464.         }
  465.  
  466.         return TRUE;
  467.     }
  468.  
  469.     return FALSE;
  470. }
  471.  
  472.  
  473. /*******************************************************************************
  474. MainKeyDownMsg
  475.     This handle all of the keyboard messages that will be used to navigate     the
  476.    table.  All other WM_KEYDOWN messages are passed onto Windows.
  477. *******************************************************************************/
  478. void MainKeyDownMsg(HWND hwnd, WPARAM wParam)
  479. {
  480.     // Process navigation commands from the keyboard.
  481.  
  482.     PITTable table = (PITTable) GetWindowLong( hwnd, 0 );
  483.     if (table)
  484.     {
  485.         switch (wParam)
  486.         {
  487.             case VK_HOME:
  488.                 table->First();
  489.                 break;
  490.             case VK_PRIOR:
  491.                 table->MoveBy(-5);
  492.                 break;
  493.             case VK_UP:
  494.                 table->Prior();
  495.                 break;
  496.             case VK_DOWN:
  497.                 table->Next();
  498.                 break;
  499.             case VK_NEXT:
  500.                 table->MoveBy(5);
  501.                 break;
  502.             case VK_END:
  503.                 table->Last();
  504.                 break;
  505.         }
  506.     }
  507. }
  508.  
  509.  
  510. /*******************************************************************************
  511. MainDestroyMsg
  512.     This destroys the datasource object, the handler object and then the table
  513.    object.
  514. *******************************************************************************/
  515. void MainDestroyMsg( HWND hwnd )
  516. {
  517.     // Release the table, the fields, and the datasource.
  518.  
  519.     PITTable table = (PITTable) GetWindowLong( hwnd, 0 );
  520.     SetWindowLong( hwnd, 0, 0 );
  521.     if (table)
  522.     {
  523.         PPITField fields = (PPITField) GetWindowLong( hwnd, 4 );
  524.         SetWindowLong( hwnd, 4, 0 );
  525.         if (fields)
  526.         {
  527.             int count = table->get_FieldCount();
  528.             int i;
  529.             for (i = 0; i < count; i++)
  530.                 fields[i]->Release();
  531.  
  532.             delete [] fields;
  533.         }
  534.  
  535.         PITDataSource datasource = (PITDataSource) GetWindowLong( hwnd, 8 );
  536.         SetWindowLong( hwnd, 8, 0 );
  537.         if (datasource)
  538.             datasource->Release();
  539.  
  540.         table->Release();
  541.     }
  542. }
  543.  
  544. //******************************************************************************
  545.